
#ifndef AFTERMATH_RANDOM_ZIGGURAT_EXPONENTIAL_HPP_INCLUDED
#define AFTERMATH_RANDOM_ZIGGURAT_EXPONENTIAL_HPP_INCLUDED

#include "ziggurat_core.hpp"

#include <cmath>
#include <cstdint>

namespace aftermath
{
    namespace random
    {
        template <std::uint_fast32_t t_n_boxes, typename t_uniform_type, typename t_bounds_type, t_bounds_type t_diameter>
        struct ziggurat_exponential
            : public ziggurat_core<t_n_boxes, ziggurat_exponential<t_n_boxes, t_uniform_type, t_bounds_type, t_diameter>, t_uniform_type, t_bounds_type, t_diameter, double>
        {
            static const std::uint_fast32_t n_boxes = t_n_boxes;
            static const t_bounds_type diameter = t_diameter;

            typedef t_uniform_type  uniform_type;
            typedef double          result_type;
            typedef t_bounds_type   bounds_type;
            typedef ziggurat_exponential<n_boxes, uniform_type, bounds_type, diameter> type;
            typedef ziggurat_core<n_boxes, type, uniform_type, bounds_type, diameter, double> base_type;

            // Inherited typedef's:
            typedef type ziggurat_impl_type;

            result_type sample_from_box_horizontal(uniform_type box_index, uniform_type uniform_random, bool& is_interior) const;

            bool is_inside_box_vertical(uniform_type box_index, result_type horizontal, uniform_type uniform_random) const;

            bool is_tail_box(uniform_type box_index) const;

            template <typename t_engine_type>
            static result_type sample_tail(uniform_type box_index, t_engine_type& uniform_generator);
        };

        template <std::uint_fast32_t t_n_boxes, typename t_engine_type, typename t_uniform_type = typename t_engine_type::result_type>
        struct ziggurat_exponential_from_engine
        {
            typedef ziggurat_exponential<t_n_boxes, t_uniform_type, std::size_t, t_engine_type::max() - t_engine_type::min()> type;
        };
    }
}

#endif // AFTERMATH_RANDOM_ZIGGURAT_EXPONENTIAL_HPP_INCLUDED
